package com.itheima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.common.constants.BusinessConstants;
import com.itheima.common.enums.HttpCodeEnum;
import com.itheima.common.exception.LeadNewsException;
import com.itheima.common.util.RequestContextUtil;
import com.itheima.common.vo.PageResultVo;
import com.itheima.wemedia.dto.WmNewsPageReqDto;
import com.itheima.wemedia.pojo.WmMaterial;
import com.itheima.wemedia.pojo.WmNews;
import com.itheima.wemedia.pojo.WmNewsMaterial;
import com.itheima.wemedia.dto.WmNewsContentNodeDto;
import com.itheima.wemedia.dto.WmNewsDtoSave;
import com.itheima.wemedia.mapper.WmMaterialMapper;
import com.itheima.wemedia.mapper.WmNewsMapper;
import com.itheima.wemedia.mapper.WmNewsMaterialMapper;
import com.itheima.wemedia.pojo.WmUser;
import com.itheima.wemedia.service.WmNewsService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @version 1.0
 * @description <p>自媒体图文内容信息 业务实现</p>
 * @package com.itheima.wemedia.service.impl
 */
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    private WmMaterialMapper wmMaterialMapper;


    /**
     * 文章分页
     *
     * @param dto
     * @return
     */
    @Override
    public PageResultVo<WmNews> listPage(WmNewsPageReqDto dto) {
        IPage<WmNews> pageParam = new Page<>(dto.getPage(), dto.getSize());
        LambdaQueryWrapper<WmNews> lqw = Wrappers.<WmNews>lambdaQuery()
                .eq(null != dto.getStatus(), WmNews::getStatus, dto.getStatus())
                .eq(WmNews::getUserId, RequestContextUtil.getUserId())
                .eq(null != dto.getChannelId(), WmNews::getChannelId, dto.getChannelId())
                .ge(null != dto.getBeginPubDate(), WmNews::getPublishTime, dto.getBeginPubDate())
                .lt(null != dto.getEndPubDate(), WmNews::getPublishTime, dto.getEndPubDate())
                .like(null != dto.getKeyword(), WmNews::getTitle, dto.getKeyword())
                .orderByDesc(WmNews::getCreatedTime);
        IPage<WmNews> pageInfo = page(pageParam, lqw);
        return PageResultVo.pageResult(dto.getPage(), dto.getSize(), pageInfo.getTotal(), pageInfo.getRecords());
    }

    /**
     * 删除文章
     *
     * @param newsId
     */
    @Override
    public void deleteById(Long newsId) {
        WmNews wmNews = getById(newsId);
        Integer status = wmNews.getStatus();
        Integer enable = wmNews.getEnable();
        if (status == BusinessConstants.WmNewsConstants.STATUS_PUBLISHED
                || enable == BusinessConstants.WmNewsConstants.ENABLE_ON) {
            throw new LeadNewsException("文件已发布或已上架，不能删除！");
        }
        //mp方法
        removeById(newsId);
        removeNewsMaterialRelationship(newsId);

    }

    /**
     * 文章上下架
     *
     * @param paramMap
     * @return
     */
    @Override
    public void downOrUp(Map<String, Long> paramMap) {
        Long newsId = paramMap.get("id");
        Long enable = paramMap.get("enable");
        if (newsId == null || null == enable || enable.intValue() < 0 || enable.intValue() > 1) {
            throw new LeadNewsException(HttpCodeEnum.PARAM_INVALID);
        }
        //id查询
        WmNews news = getById(newsId);
        //文章发布才能修改
        if (news.getStatus() != BusinessConstants.WmNewsConstants.STATUS_PUBLISHED) {
            throw new LeadNewsException("文章处于发布状态，不能上下架!");
        }
        //更新== 状态
        WmNews updatePojo = new WmNews();
        updatePojo.setId(newsId);
        if (enable == 0){
            //修改为下架
            updatePojo.setEnable(BusinessConstants.WmNewsConstants.ENABLE_OFF);
            //待申诉
            updatePojo.setStatus(BusinessConstants.WmNewsConstants.STATUS_SUBMIT);
            updatePojo.setSubmitedTime(LocalDateTime.now());
        }else{
            updatePojo.setEnable(BusinessConstants.WmNewsConstants.ENABLE_ON);
        }
        updateById(updatePojo);
    }


    /**
     * 发布文章
     *
     * @param draft
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public Long submit(boolean draft, WmNewsDtoSave dto) {
        //=============保存文章数据
        WmNews pojo = new WmNews();
        BeanUtils.copyProperties(dto, pojo);
        pojo.setUserId(RequestContextUtil.getUserId());
        pojo.setStatus(draft ? 0 : 1);
        pojo.setCreatedTime(LocalDateTime.now());
        pojo.setEnable(BusinessConstants.WmNewsConstants.ENABLE_OFF);
        //判断封面，逗号拼接
        if (!CollectionUtils.isEmpty(dto.getImages())) {
            pojo.setImages(String.join(",", dto.getImages()));
        }
        //文章布局类型 ===== 封面
        if (dto.getType() == BusinessConstants.WmNewsConstants.TYPE_AUTO) {
            setPojoType(pojo, dto);
        }
        LocalDateTime now = LocalDateTime.now();
        if (!draft) {
            pojo.setSubmitedTime(now);
        }
        if (null == dto.getId()) {
            pojo.setCreatedTime(now);
            save(pojo);
        } else {
            updateById(pojo);
            //删除
            removeNewsMaterialRelationship(pojo.getId());
        }

        saveWmNewsMaterialRelationship(pojo);

        return pojo.getId();
    }

    /**
     * 删除文章与素材的关系
     *
     * @param
     */
    private void removeNewsMaterialRelationship(Long id) {
        wmNewsMaterialMapper.deleteByMap(Collections.singletonMap("news_id", id));

    }


    /**
     * 添加文章素材关系
     *
     * @param pojo
     */
    private void saveWmNewsMaterialRelationship(WmNews pojo) {
        Set<String> imageSet = new HashSet<>();
        String images = pojo.getImages();
        List<String> coverList = new ArrayList<>();
        if (StringUtils.isEmpty(images)) {
            String[] coverArray = images.split(",");
            Collections.addAll(coverList, coverArray);
            //去前缀
            coverList = coverList.stream().map(WmNewsServiceImpl::removePrefix).collect(Collectors.toList());
            imageSet.addAll(coverList);
        }
        List<String> contentImages = getContentImages(pojo.getContent());
        //去前缀
        contentImages = contentImages.stream().map(WmNewsServiceImpl::removePrefix).collect(Collectors.toList());

        imageSet.addAll(contentImages);

        Map<String, Long> materialMap = getMaterialMap(imageSet);

        Long wmNewsId = pojo.getId();
        //封面图片
        addRelationShip(wmNewsId, coverList, materialMap, 1);
        //内容图片
        addRelationShip(wmNewsId, contentImages, materialMap, 0);
    }

    /**
     * 添加文章素材关系
     *
     * @param wmNewsId
     * @param contentImages
     * @param materialMap
     * @param type
     */
    private void addRelationShip(Long wmNewsId, List<String> contentImages, Map<String, Long> materialMap, int type) {
        contentImages.forEach(WmNewsServiceImpl::removePrefix);
        for (int i = 0; i < contentImages.size(); i++) {
            WmNewsMaterial newsMaterial = new WmNewsMaterial();
            newsMaterial.setMaterialId(materialMap.get(contentImages.get(i)));
            newsMaterial.setNewsId(wmNewsId);
            newsMaterial.setOrd(i + 1);
            newsMaterial.setType(type);
            wmNewsMaterialMapper.insert(newsMaterial);
        }
    }

    private Map<String, Long> getMaterialMap(Set<String> imageSet) {
        Map<String, Long> resultMap = new HashMap<>();
        LambdaQueryWrapper<WmMaterial> lqw = new LambdaQueryWrapper<>();
        lqw.in(WmMaterial::getUrl, imageSet);
        List<WmMaterial> wmMaterials = wmMaterialMapper.selectList(lqw);
        if (CollectionUtils.isEmpty(wmMaterials)) {
            resultMap = wmMaterials.stream().collect(Collectors.toMap(WmMaterial::getUrl, WmMaterial::getId));
        }
        return resultMap;
    }


    /**
     * 文章布局类型 ===== 封面
     *
     * @param pojo
     * @param dto
     */
    private void setPojoType(WmNews pojo, WmNewsDtoSave dto) {
        List<String> contentImageList = getContentImages(dto.getContent());

        int size = contentImageList.size();
        if (size < 1) {
            pojo.setType(BusinessConstants.WmNewsConstants.TYPE_NONE_IMG);
            pojo.setImages("");
        } else if (size < 3) {
            pojo.setType(BusinessConstants.WmNewsConstants.TYPE_SINGLE_IMG);
        } else {
            pojo.setType(BusinessConstants.WmNewsConstants.TYPE_MULTIPLE_IMG);
        }
        pojo.setImages(contentImageList.stream().limit(3).collect(Collectors.joining(",")));
    }


    /**
     * 提取文章图片
     *
     * @param
     */
    private List<String> getContentImages(String content) {
        List<WmNewsContentNodeDto> contentList = JSON.parseArray(content, WmNewsContentNodeDto.class);
        return contentList.stream().filter(node -> "image".equals(node.getType()))
                .map(WmNewsContentNodeDto::getValue).collect(Collectors.toList());
    }

    /**
     * 去除完整路径
     *
     * @param url
     * @return
     */
    private static String removePrefix(String url) {
        //http://192.168.211.128:8080/group1/M00/00/00/wKjTgGK4BGuASyi-AAiWSBNgF8M620.png
        //http://192.168.211.128/group1/M00/00/00/wKjTgGK4BGuASyi-AAiWSBNgF8M620.png
        //http://127.0.0.1/group1/M00/00/00/wKjTgGK4BGuASyi-AAiWSBNgF8M620.png
        return url.replaceAll("http://((\\d){1,3}\\.){3}(\\d){1,3}:?(\\d){0,5}\\/", "");
    }
}
